<?php
abstract class Exts_Controller_GenericSecureController extends Exts_Controller_SecureAction
{
	protected $_model;
	protected $_showableAttributesAtListContext = array();
	protected $_newCreateFormFactory;
	protected $_newUpdateFormFactory;
	protected $_defaultUrl;
	protected $_urlBeforeSave;
	protected $_idReqKey = "id";

	/*
	 * ExtendedClass::_getModel(); retorna el nombre de la clase modelo asociado
	 * al controller (okok, es chato)
	 */
	protected function _getModel (){
		return $this->_model;
	}

	/*
	 * ExtendedClass::_getShowableAttributesAtListContext(); retorna un array
	 * con los atributos del objeto a mostrar en el listado.
	 */
	protected function _getShowableAttributesAtListContext (){
		return $this->_showableAttributesAtListContext;
	}

	/*
	 * ExtendedClass::_createForm(); retorna un form
	 * con la configuracion para hacer un alta.
	 */
	protected function _newCreateForm(){
		if (empty($this->_newCreateFormFactory)) $this->_newCreateFormFactory = $this->_newUpdateFormFactory;

		$prod_class = new ReflectionClass( $this->_newCreateFormFactory );
        $methods = $prod_class->getMethods();
		
		foreach ($methods as $method) {
		      if ($method->getName () == 'newCreateForm' && $method->isStatic()) return $method->invoke(NULL);	
		}
	 
        throw new Exception ("$this->_newCreateFormFactory debe impementar el metodo estatico newCreateForm"); 
	}

	/*
	 * ExtendedClass::_newUpdateForm(); retorna un form
	 * con la configuracion para actualizar.
	 */
	protected function _newUpdateForm(){
		if (empty($this->_newUpdateFormFactory)) $this->_newUpdateFormFactory = $this->_newCreateFormFactory;

	    $prod_class = new ReflectionClass( $this->_newCreateFormFactory );
        $methods = $prod_class->getMethods();
        
        foreach ($methods as $method) {
              if ($method->getName () == 'newUpdateForm' && $method->isStatic()) return $method->invoke(NULL);  
        }
     
        throw new Exception ("$this->_newCreateFormFactory debe impementar el metodo estatico newUpdateForm");
	}

	/*
	 * ExtendedClass::_validateCreateData(); retorna un boolean
	 * luego de la validacion del request al momento de crear
	 */
	protected function _validateCreateData($request){
		return true;
	}

	/*
	 * ExtendedClass::_validateUpdateData(); retorna un boolean
	 * luego de la validacion del request al momento de actualizar
	 */
	protected function _validateUpdateData($request){
		return true;
	}

	/*
	 * ExtendedClass::_defaultRedirectUrl(); retorna una url
	 * donde se va a redireccionar por defecto
	 */
	protected function _defaultRedirectUrl(){
		return $this->_defaultUrl;
	}
	/*
	 * ExtendedClass::_redirectBeforeSave($request);
	 * url para redireccionar luego de insert / update
	 */
	
	protected function _redirectBeforeSave($request){
		if(empty($this->_urlBeforeSave)){
			return $this->_defaultRedirectUrl();
		}
		return $this->_urlBeforeSave;
	}
	
	/*
	 * ExtendedClass::_expectedKeysFilters(); retorna relaciones
	 * entre claves y formas de filtrar
	 */
	
	protected function _expectedKeysFilters () {
		return array(
            'key' => array( 
		      'column' => 'name',
		      'strategy' => Exts_Filters_FilterCommandFactory::likeAnyWhere()
		  )
        );
	}

	/*
	 * ExtendedClass::_idRequestKey(); la clave donde figura el id
	 * en el request
	 */
	protected function _idRequestKey()
	{
		return $this->_idReqKey;
	}

	/*
	 * ExtendedClass::_getModelInstance();
	 * retorna una instancia del modelo (basado en _getModel())
	 */
	protected function _getModelInstance()
	{
		$modelClass = $this->_getModel();
		return new $modelClass();
	}
	/*
	 * ExtendedClass::_beforeSave($request);
	 * punto de extension permite modificar valores del request antes de salvar
	 */
	protected function _beforeSave ($request)
	{
		return $request;
	}
	/*
	 * ExtendedClass::_afterSave($request);
	 * punto de extension permite trabajar con valores del request luego de guardar
	 */
	protected function _afterSave ($request)
	{
		return $request;
	}

	protected function _manageError(Exception $exception) {
		throw $exception;
	}

	/*
	 * ExtendedClass::listAction($request);
	 * lista
	 */

	public function listAction ()
	{
		try {
			$model = $this->_getModelInstance();
			$query = $model->getQueryList();
			$filters = $this->_expectedKeysFilters();
			
			$request = $this->_getAllParams();
			foreach($filters as $key => $filter){
				if (array_key_exists('fixedValue', $filter)){
					$filterCommand = $filter['strategy'];
					
					$query = $filterCommand->applyFilter($query, $filter['column'], $filter['fixedValue'] );
				}
				else if (!empty($request[$key])){
					$filterCommand = $filter['strategy'];
					$query = $filterCommand->applyFilter($query, $filter['column'], $request[$key] );
				} 
				else if (array_key_exists('default', $filter)){
						$filterCommand = $filter['strategy'];
						$query = $filterCommand->applyFilter($query, $filter['column'], $filter['default'] );
				}
				
			}
			$this->view->paginator = new Exts_Paginator( $query, $this->_page, $this->view );
			$this->view->attributes = $this->_getShowableAttributesAtListContext();
		}
		catch (Exception $e){
			return $this->_manageError($e);
		}
	}

	/*
	 * ExtendedClass::createAction($request);
	 * alta
	 */

	public function createAction()
	{
		try {
			$form = $this->_newCreateForm();
			if ( $this->getRequest()->isPost() ) {
				$request = $this->getRequest()->getParams();
				if( $form->isValid($request) ) {
					$this->_validateCreateData($request);
					$model = $this->_getModelInstance();
					$request = $this->_beforeSave($request);
					$model->save($request);
					$request = $this->_afterSave($request);
					return $this->_redirect($this->_redirectBeforeSave($request));
				}
			}
			$this->view->form = $form;
		}
		catch (Exception $e){
			return $this->_manageError($e);
		}
	}

	/*
	 * ExtendedClass::createAction($request);
	 * modificacion
	 */
	public function updateAction()
	{
		try{
			if( ! $this->_hasParam( $this->_idRequestKey() )) {
				return $this->_redirect( $this->_defaultRedirectUrl() );
			}

			$form = $this->_newUpdateForm();
			$form->forUpdate($this->_getParam($this->_idRequestKey()));

			$model = $this->_getModelInstance();
			
			if ( $this->getRequest()->isPost() ) {
				if( $form->isValid($this->getRequest()->getParams()) ) {
					$bind = $form->getValues();
					$request = $this->_beforeSave($bind);
					$model->save($bind);
					$request = $this->_afterSave($bind);
					return $this->_redirect($this->_redirectBeforeSave($request));
				}
				$form->populate($form->getValues());
			} else {
				$row = $model->find( $this->_getParam($this->_idRequestKey() ))->current();
				if (count( $row )) {
					$form->populate( $row->toArray() );
				}
			}

			$this->view->form = $form;
		}
		catch (Exception $e){
			return $this->_manageError($e);
		}
	}
	/*
	 * ExtendedClass::deleteAction($request);
	 * baja
	 */
	public function deleteAction()
	{/*
		try {
			if( ! $this->_hasParam( $this->_idRequestKey() )) {
				return $this->_redirect( $this->_defaultRedirectUrl() );
			}
			$model = $this->_getModelInstance();
			$model->delete($this->_getParam($this->_idRequestKey()));
			return $this->_redirect($this->_redirectBeforeSave($request));
		}
		catch (Exception $e){
			return $this->_manageError($e);
		}*/
	}
}
